浮点数和机器精度 您所在的位置:网站首页 浮点 精度 浮点数和机器精度

浮点数和机器精度

2024-06-02 05:31| 来源: 网络整理| 查看: 265

在优化代码的过程中再次遇到数据瓶颈——精度问题,不得不再温习一下这个自以为很了解的主题:浮点数和精度。

为什么一个简单的整数,在计算机内的值并不一致?例如,实际数值558783388,在float下是558783360,而

log2( 558783388) ans = 29.0577 log2( 558783360) ans = 29.0577在double下是5.587833745970526e+08,因为double精度比float高,所以更加逼近实际数值

误差

这一切就是因为二进制,用二进制表示一个数(十进制数),是有误差的。再举一个例子:

double a=0.2;在内存中,我们可以看到a对应的存储区数据是:

9A 99 99 99 99 99 C9 3F这是小端(little endian)存储方式,换成高位在前:

3F C9 99 99 99 99 99 9A

double在内存中的形式如下(详细请看IEEE 754浮点运算标准):

63(1 bits) 62~52(11 bits) 51~0(52 bits) 符号位 指数位(阶码) 尾数 (-1022~1023)

可见符号位为0,指数位是0x3FC,即1020,减去2^10-1,即1023,得指数为-3;尾数是999999999999A。所以完整的数字就是16进制的1.999999999999A乘上2^-3,得

a=0.2000 0000 0000 0000 1110 2230 2462 5157已经可以看到用double表示0.2时存在的误差。这个例子说明在用有限字长的二进制浮点数表示任意实数a可能引入误差。设实数a的指数为e,尾数位数为n,显然:误差1

的最小浮点数ε。显然double的机器精度是1/2^52。float的机器精度是1/2^23。上面的例子就是,十进制数的0.2后面第17位开始有误差,即10^-16:

10^-16 ans = 1.0000e-16 2^-52 ans = 2.2204e-16double而今不足以确定其精度,其最小只能到:

10^-15 ans = 1.0000e-15上面说的是小数位,更科学的说法是有效数字。因为小数点前默认有个1,所以float的有效数字是24bit,对应8位十进制有效数字; double的有效数字是53bit,对应16位十进制有效数字。也就是说,如果一个实数的有效数字超过8位,用单精度浮点数来表示的话,就会产生误差!同样,如果一个实数的有效数字超过16位,用双精度浮点数来表示,也会产生误差!

NaN和INF

在matlab中经常遇到,计算后的矩阵中存在这两个符号。它们属于特殊的浮点数。一旦阶码为0或全1,就会出现特殊浮点数。

# 当指数全0的情况下,如果尾数为0,根据符号位不同可以分为+0和-0;如果尾数为非0,即尾数部分不假设前面存在小数点前的1。或者说这些数太接近0了,因为指数已经不能再小。例如一个double变量在内存中的表示(十六进制):

00 00 00 00 00 00 00 01阶码为0,指数直接等于-1022,尾数为1/2^52,故结果为:

4.9406564584124654e-324 # 当指数全1的情况下,如果尾数为0,表示无穷,根据符号位确定是+INF、-INF;如果尾数非0,表示NaN非数值

归纳如下表:浮点数的特殊值(double)

符号位 阶码 尾数 数值 0 0 0 +0 1 0 0 -0 0 2047 0 +∞ 1 2047 0 -∞ 0 2047 非0 NaN

总结

float和int都是32bit,但float的尾数只用了23bit。int的精度高于float,float的表示范围大于int。float牺牲精度换取了更大的表示范围。 double的尾数是52bit,高于32bit的int,所以用dobule表示int不会有精度损失。 double是科学计算的常用类型,了解double的内在和限制,有助于我们更好地使用它。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有